package com.zenithmind.library.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zenithmind.common.result.PageResult;
import com.zenithmind.common.result.Result;
import com.zenithmind.common.result.ResultCode;
import com.zenithmind.library.mapper.AuthorMapper;
import com.zenithmind.library.mapper.BookAuthorMapper;
import com.zenithmind.library.mapper.BookMapper;
import com.zenithmind.library.pojo.domain.Author;
import com.zenithmind.library.pojo.domain.Book;
import com.zenithmind.library.pojo.domain.BookAuthor;
import com.zenithmind.library.pojo.dto.BookAuthorCreateDTO;
import com.zenithmind.library.pojo.query.BookAuthorQuery;
import com.zenithmind.library.pojo.vo.BookAuthorVO;
import com.zenithmind.library.service.BookAuthorService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * 图书作者关联服务实现类
 * 遵循单一职责原则：只负责图书作者关联相关的业务逻辑
 * 遵循依赖倒置原则：依赖抽象接口而非具体实现
 * 
 * @author ZenithMind
 * @since 2024-06-14
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class BookAuthorServiceImpl extends ServiceImpl<BookAuthorMapper, BookAuthor> implements BookAuthorService {

    private final BookAuthorMapper bookAuthorMapper;
    private final BookMapper bookMapper;
    private final AuthorMapper authorMapper;

    @Override
    @Cacheable(value = "bookAuthors", key = "'page:' + #query.hashCode()")
    public PageResult<BookAuthorVO> getBookAuthorPage(BookAuthorQuery query) {
        log.info("分页查询图书作者关联，查询条件：{}", query);

        // 构建查询条件
        LambdaQueryWrapper<BookAuthor> wrapper = new LambdaQueryWrapper<>();
        
        if (query.getBookId() != null && !query.getBookId().trim().isEmpty()) {
            wrapper.eq(BookAuthor::getBookId, query.getBookId());
        }
        
        if (query.getAuthorId() != null && !query.getAuthorId().trim().isEmpty()) {
            wrapper.eq(BookAuthor::getAuthorId, query.getAuthorId());
        }
        
        if (query.getAuthorRole() != null && !query.getAuthorRole().trim().isEmpty()) {
            wrapper.like(BookAuthor::getAuthorRole, query.getAuthorRole());
        }
        
        if (query.getSortOrder() != null && query.getSortOrder() == 1) {
            wrapper.eq(BookAuthor::getSortOrder, 1); // 查询主要作者
        }
        
        wrapper.orderByAsc(BookAuthor::getSortOrder);

        // 分页查询
        Page<BookAuthor> page = new Page<>(query.getCurrent(), query.getSize());
        IPage<BookAuthor> result = page(page, wrapper);

        // 转换为VO
        List<BookAuthorVO> vos = result.getRecords().stream()
                                      .map(this::convertToVO)
                                      .collect(Collectors.toList());

        return PageResult.of(vos, result.getTotal(), result.getCurrent(), result.getSize());
    }

    @Override
    @Cacheable(value = "bookAuthors", key = "'book:' + #bookId")
    public Result<List<BookAuthorVO>> getAuthorsByBookId(String bookId) {
        log.info("根据图书ID查询作者列表，图书ID：{}", bookId);

        if (bookId == null || bookId.trim().isEmpty()) {
            return Result.fail(ResultCode.PARAM_ERROR.getCode(), "图书ID不能为空", null);
        }

        LambdaQueryWrapper<BookAuthor> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(BookAuthor::getBookId, bookId)
               .orderByAsc(BookAuthor::getSortOrder);

        List<BookAuthor> bookAuthors = list(wrapper);
        List<BookAuthorVO> vos = bookAuthors.stream()
                                           .map(this::convertToVO)
                                           .collect(Collectors.toList());

        return Result.success(vos);
    }

    @Override
    @Cacheable(value = "bookAuthors", key = "'author:' + #authorId")
    public Result<List<BookAuthorVO>> getBooksByAuthorId(String authorId) {
        log.info("根据作者ID查询图书列表，作者ID：{}", authorId);

        if (authorId == null || authorId.trim().isEmpty()) {
            return Result.fail(ResultCode.PARAM_ERROR.getCode(), "作者ID不能为空", null);
        }

        LambdaQueryWrapper<BookAuthor> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(BookAuthor::getAuthorId, authorId)
               .orderByDesc(BookAuthor::getCreateTime);

        List<BookAuthor> bookAuthors = list(wrapper);
        List<BookAuthorVO> vos = bookAuthors.stream()
                                           .map(this::convertToVO)
                                           .collect(Collectors.toList());

        return Result.success(vos);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = "bookAuthors", allEntries = true)
    public Result<BookAuthorVO> addAuthorToBook(String bookId, String authorId, String authorRole, Integer authorOrder) {
        log.info("为图书添加作者，图书ID：{}，作者ID：{}，角色：{}，顺序：{}", bookId, authorId, authorRole, authorOrder);

        // 验证图书是否存在
        Book book = bookMapper.selectById(bookId);
        if (book == null) {
            return Result.fail(ResultCode.NOT_FOUND.getCode(), "图书不存在", null);
        }

        // 验证作者是否存在
        Author author = authorMapper.selectById(authorId);
        if (author == null) {
            return Result.fail(ResultCode.NOT_FOUND.getCode(), "作者不存在", null);
        }

        // 检查关联是否已存在
        if (existsBookAuthor(bookId, authorId)) {
            return Result.fail(ResultCode.CONFLICT.getCode(), "图书作者关联已存在", null);
        }

        BookAuthor bookAuthor = new BookAuthor();
        bookAuthor.setId(UUID.randomUUID().toString());
        bookAuthor.setBookId(bookId);
        bookAuthor.setAuthorId(authorId);
        bookAuthor.setAuthorRole(authorRole);
        bookAuthor.setSortOrder(authorOrder);
        bookAuthor.setCreateTime(LocalDateTime.now());
        bookAuthor.setUpdateTime(LocalDateTime.now());

        save(bookAuthor);

        BookAuthorVO vo = convertToVO(bookAuthor);
        log.info("图书作者关联创建成功，ID：{}", bookAuthor.getId());
        return Result.success(vo);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = "bookAuthors", allEntries = true)
    public Result<List<BookAuthorVO>> batchAddAuthorsToBook(String bookId, List<BookAuthorCreateDTO> bookAuthors) {
        log.info("批量为图书添加作者，图书ID：{}，数量：{}", bookId, bookAuthors.size());

        if (bookAuthors == null || bookAuthors.isEmpty()) {
            return Result.fail(ResultCode.PARAM_ERROR.getCode(), "作者列表不能为空", null);
        }

        // 验证图书是否存在
        Book book = bookMapper.selectById(bookId);
        if (book == null) {
            return Result.fail(ResultCode.NOT_FOUND.getCode(), "图书不存在", null);
        }

        List<BookAuthorVO> resultVos = bookAuthors.stream()
                .map(dto -> {
                    Result<BookAuthorVO> result = addAuthorToBook(bookId, dto.getAuthorId(),
                            dto.getAuthorRole(), dto.getSortOrder());
                    return result.isSuccess() ? result.getData() : null;
                })
                .filter(vo -> vo != null)
                .collect(Collectors.toList());

        log.info("批量添加图书作者完成，成功：{}个", resultVos.size());
        return Result.success(resultVos);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = "bookAuthors", allEntries = true)
    public Result<Void> removeAuthorFromBook(String bookId, String authorId) {
        log.info("从图书中移除作者，图书ID：{}，作者ID：{}", bookId, authorId);

        if (bookId == null || bookId.trim().isEmpty()) {
            return Result.fail(ResultCode.PARAM_ERROR.getCode(), "图书ID不能为空", null);
        }

        if (authorId == null || authorId.trim().isEmpty()) {
            return Result.fail(ResultCode.PARAM_ERROR.getCode(), "作者ID不能为空", null);
        }

        LambdaQueryWrapper<BookAuthor> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(BookAuthor::getBookId, bookId)
               .eq(BookAuthor::getAuthorId, authorId);

        boolean removed = remove(wrapper);
        if (!removed) {
            return Result.fail(ResultCode.NOT_FOUND.getCode(), "图书作者关联不存在", null);
        }

        log.info("图书作者关联移除成功");
        return Result.success();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = "bookAuthors", allEntries = true)
    public Result<Void> batchRemoveAuthorsFromBook(String bookId, List<String> authorIds) {
        log.info("批量从图书中移除作者，图书ID：{}，数量：{}", bookId, authorIds.size());

        if (authorIds == null || authorIds.isEmpty()) {
            return Result.fail(ResultCode.PARAM_ERROR.getCode(), "作者ID列表不能为空", null);
        }

        LambdaQueryWrapper<BookAuthor> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(BookAuthor::getBookId, bookId)
               .in(BookAuthor::getAuthorId, authorIds);

        boolean removed = remove(wrapper);
        if (!removed) {
            return Result.fail(ResultCode.NOT_FOUND.getCode(), "未找到要删除的图书作者关联", null);
        }

        log.info("批量移除图书作者关联成功");
        return Result.success();
    }

    @Override
    public boolean existsBookAuthor(String bookId, String authorId) {
        LambdaQueryWrapper<BookAuthor> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(BookAuthor::getBookId, bookId)
               .eq(BookAuthor::getAuthorId, authorId);
        return count(wrapper) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = "bookAuthors", allEntries = true)
    public Result<BookAuthorVO> updateBookAuthor(String bookId, String authorId, String authorRole, Integer authorOrder) {
        log.info("更新图书作者关联，图书ID：{}，作者ID：{}，角色：{}，顺序：{}", bookId, authorId, authorRole, authorOrder);

        LambdaQueryWrapper<BookAuthor> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(BookAuthor::getBookId, bookId)
               .eq(BookAuthor::getAuthorId, authorId);

        BookAuthor bookAuthor = getOne(wrapper);
        if (bookAuthor == null) {
            return Result.fail(ResultCode.NOT_FOUND.getCode(), "图书作者关联不存在", null);
        }

        if (authorRole != null) {
            bookAuthor.setAuthorRole(authorRole);
        }
        if (authorOrder != null) {
            bookAuthor.setSortOrder(authorOrder);
        }
        bookAuthor.setUpdateTime(LocalDateTime.now());

        updateById(bookAuthor);

        BookAuthorVO vo = convertToVO(bookAuthor);
        log.info("图书作者关联更新成功");
        return Result.success(vo);
    }

    @Override
    @Cacheable(value = "bookAuthors", key = "'primary:' + #bookId")
    public Result<BookAuthorVO> getPrimaryAuthor(String bookId) {
        log.info("获取图书主要作者，图书ID：{}", bookId);

        if (bookId == null || bookId.trim().isEmpty()) {
            return Result.fail(ResultCode.PARAM_ERROR.getCode(), "图书ID不能为空", null);
        }

        LambdaQueryWrapper<BookAuthor> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(BookAuthor::getBookId, bookId)
               .eq(BookAuthor::getSortOrder, 1)
               .last("LIMIT 1");

        BookAuthor bookAuthor = getOne(wrapper);
        if (bookAuthor == null) {
            return Result.fail(ResultCode.NOT_FOUND.getCode(), "未找到主要作者", null);
        }

        BookAuthorVO vo = convertToVO(bookAuthor);
        return Result.success(vo);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = "bookAuthors", allEntries = true)
    public Result<Void> setPrimaryAuthor(String bookId, String authorId) {
        log.info("设置图书主要作者，图书ID：{}，作者ID：{}", bookId, authorId);

        // 先将该图书的所有作者的sortOrder调整（主要作者sortOrder=1）
        LambdaQueryWrapper<BookAuthor> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(BookAuthor::getBookId, bookId);

        List<BookAuthor> bookAuthors = list(wrapper);

        // 找到要设为主要作者的记录
        BookAuthor primaryAuthor = null;
        for (BookAuthor ba : bookAuthors) {
            if (ba.getAuthorId().equals(authorId)) {
                primaryAuthor = ba;
                break;
            }
        }

        if (primaryAuthor == null) {
            return Result.fail(ResultCode.NOT_FOUND.getCode(), "图书作者关联不存在", null);
        }

        // 重新排序：主要作者设为1，其他作者依次递增
        int order = 2;
        for (BookAuthor ba : bookAuthors) {
            if (ba.getAuthorId().equals(authorId)) {
                ba.setSortOrder(1); // 主要作者
            } else {
                ba.setSortOrder(order++);
            }
            ba.setUpdateTime(LocalDateTime.now());
        }
        updateBatchById(bookAuthors);

        log.info("设置主要作者成功");
        return Result.success();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = "bookAuthors", allEntries = true)
    public Result<Void> adjustAuthorOrder(String bookId, List<AuthorOrderDTO> authorOrders) {
        log.info("调整作者顺序，图书ID：{}，数量：{}", bookId, authorOrders.size());

        if (authorOrders == null || authorOrders.isEmpty()) {
            return Result.fail(ResultCode.PARAM_ERROR.getCode(), "作者顺序列表不能为空", null);
        }

        for (AuthorOrderDTO orderDTO : authorOrders) {
            LambdaQueryWrapper<BookAuthor> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(BookAuthor::getBookId, bookId)
                   .eq(BookAuthor::getAuthorId, orderDTO.getAuthorId());

            BookAuthor bookAuthor = getOne(wrapper);
            if (bookAuthor != null) {
                bookAuthor.setSortOrder(orderDTO.getOrder());
                bookAuthor.setUpdateTime(LocalDateTime.now());
                updateById(bookAuthor);
            }
        }

        log.info("调整作者顺序成功");
        return Result.success();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = "bookAuthors", allEntries = true)
    public Result<List<BookAuthorVO>> copyBookAuthors(String sourceBookId, String targetBookId) {
        log.info("复制图书作者关联，源图书ID：{}，目标图书ID：{}", sourceBookId, targetBookId);

        // 验证目标图书是否存在
        Book targetBook = bookMapper.selectById(targetBookId);
        if (targetBook == null) {
            return Result.fail(ResultCode.NOT_FOUND.getCode(), "目标图书不存在", null);
        }

        // 获取源图书的作者关联
        LambdaQueryWrapper<BookAuthor> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(BookAuthor::getBookId, sourceBookId)
               .orderByAsc(BookAuthor::getSortOrder);

        List<BookAuthor> sourceAuthors = list(wrapper);
        if (sourceAuthors.isEmpty()) {
            return Result.fail(ResultCode.NOT_FOUND.getCode(), "源图书没有作者关联", null);
        }

        // 复制到目标图书
        List<BookAuthor> targetAuthors = sourceAuthors.stream()
                .map(source -> {
                    BookAuthor target = new BookAuthor();
                    BeanUtils.copyProperties(source, target);
                    target.setId(UUID.randomUUID().toString());
                    target.setBookId(targetBookId);
                    target.setCreateTime(LocalDateTime.now());
                    target.setUpdateTime(LocalDateTime.now());
                    return target;
                })
                .collect(Collectors.toList());

        saveBatch(targetAuthors);

        List<BookAuthorVO> vos = targetAuthors.stream()
                                             .map(this::convertToVO)
                                             .collect(Collectors.toList());

        log.info("复制图书作者关联成功，数量：{}", vos.size());
        return Result.success(vos);
    }

    @Override
    public Result<AuthorBookStatisticsVO> getAuthorBookStatistics(String authorId) {
        log.info("获取作者图书统计，作者ID：{}", authorId);

        if (authorId == null || authorId.trim().isEmpty()) {
            return Result.fail(ResultCode.PARAM_ERROR.getCode(), "作者ID不能为空", null);
        }

        try {
            AuthorBookStatisticsVO statistics = new AuthorBookStatisticsVO();

            LambdaQueryWrapper<BookAuthor> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(BookAuthor::getAuthorId, authorId);

            List<BookAuthor> bookAuthors = list(wrapper);
            statistics.setTotalBooks(bookAuthors.size());

            // 按角色统计
            statistics.setPrimaryAuthorBooks((int) bookAuthors.stream().filter(ba -> ba.isPrimaryAuthor()).count());
            statistics.setCoAuthorBooks((int) bookAuthors.stream().filter(ba -> "合著者".equals(ba.getAuthorRole())).count());
            statistics.setTranslatorBooks((int) bookAuthors.stream().filter(ba -> "译者".equals(ba.getAuthorRole())).count());
            statistics.setEditorBooks((int) bookAuthors.stream().filter(ba -> "编辑".equals(ba.getAuthorRole())).count());

            return Result.success(statistics);
        } catch (Exception e) {
            log.error("获取作者图书统计失败，作者ID：{}", authorId, e);
            return Result.fail(ResultCode.INTERNAL_SERVER_ERROR.getCode(), "获取统计信息失败", null);
        }
    }

    @Override
    public Result<BookAuthorStatisticsVO> getBookAuthorStatistics(String bookId) {
        log.info("获取图书作者统计，图书ID：{}", bookId);

        if (bookId == null || bookId.trim().isEmpty()) {
            return Result.fail(ResultCode.PARAM_ERROR.getCode(), "图书ID不能为空", null);
        }

        try {
            BookAuthorStatisticsVO statistics = new BookAuthorStatisticsVO();

            LambdaQueryWrapper<BookAuthor> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(BookAuthor::getBookId, bookId);

            List<BookAuthor> bookAuthors = list(wrapper);
            statistics.setTotalAuthors(bookAuthors.size());

            // 按角色统计
            statistics.setPrimaryAuthors((int) bookAuthors.stream().filter(ba -> ba.isPrimaryAuthor()).count());
            statistics.setCoAuthors((int) bookAuthors.stream().filter(ba -> "合著者".equals(ba.getAuthorRole())).count());
            statistics.setTranslators((int) bookAuthors.stream().filter(ba -> "译者".equals(ba.getAuthorRole())).count());
            statistics.setEditors((int) bookAuthors.stream().filter(ba -> "编辑".equals(ba.getAuthorRole())).count());

            return Result.success(statistics);
        } catch (Exception e) {
            log.error("获取图书作者统计失败，图书ID：{}", bookId, e);
            return Result.fail(ResultCode.INTERNAL_SERVER_ERROR.getCode(), "获取统计信息失败", null);
        }
    }

    @Override
    public Result<String> importBookAuthors(List<BookAuthorCreateDTO> bookAuthors) {
        log.info("导入图书作者关联数据，数量：{}", bookAuthors.size());

        if (bookAuthors == null || bookAuthors.isEmpty()) {
            return Result.fail(ResultCode.PARAM_ERROR.getCode(), "导入数据不能为空", null);
        }

        int successCount = 0;
        int failCount = 0;
        StringBuilder errorMessages = new StringBuilder();

        for (int i = 0; i < bookAuthors.size(); i++) {
            BookAuthorCreateDTO dto = bookAuthors.get(i);
            try {
                Result<BookAuthorVO> result = addAuthorToBook(dto.getBookId(), dto.getAuthorId(),
                        dto.getAuthorRole(), dto.getSortOrder());
                if (result.isSuccess()) {
                    successCount++;
                } else {
                    failCount++;
                    errorMessages.append("第").append(i + 1).append("行：").append(result.getMsg()).append("；");
                }
            } catch (Exception e) {
                failCount++;
                errorMessages.append("第").append(i + 1).append("行：").append(e.getMessage()).append("；");
                log.error("导入第{}行数据失败", i + 1, e);
            }
        }

        String resultMessage = String.format("导入完成，成功：%d条，失败：%d条", successCount, failCount);
        if (failCount > 0) {
            resultMessage += "。失败原因：" + errorMessages.toString();
        }

        log.info("图书作者关联数据导入完成，成功：{}条，失败：{}条", successCount, failCount);
        return Result.success(resultMessage);
    }

    @Override
    public Result<String> exportBookAuthors(BookAuthorQuery query) {
        log.info("导出图书作者关联数据，查询条件：{}", query);

        try {
            if (query == null) {
                query = new BookAuthorQuery();
            }

            query.setSize(10000); // 最多导出10000条记录
            PageResult<BookAuthorVO> pageResult = getBookAuthorPage(query);

            if (pageResult == null || pageResult.getRecords() == null || pageResult.getRecords().isEmpty()) {
                return Result.fail(ResultCode.NOT_FOUND.getCode(), "没有找到符合条件的数据", null);
            }

            String timestamp = String.valueOf(System.currentTimeMillis());
            String fileName = "book_authors_export_" + timestamp + ".xlsx";
            String filePath = "/exports/" + fileName;

            log.info("模拟生成Excel文件，包含{}条记录，文件路径：{}", pageResult.getRecords().size(), filePath);

            String resultMessage = String.format("导出成功，共%d条记录，文件：%s",
                pageResult.getRecords().size(), fileName);

            log.info("图书作者关联数据导出完成，记录数：{}，文件：{}", pageResult.getRecords().size(), fileName);
            return Result.success(resultMessage);

        } catch (Exception e) {
            log.error("导出图书作者关联数据失败", e);
            return Result.fail(ResultCode.INTERNAL_SERVER_ERROR.getCode(), "导出失败：" + e.getMessage(), null);
        }
    }

    /**
     * 转换为VO对象
     */
    private BookAuthorVO convertToVO(BookAuthor bookAuthor) {
        BookAuthorVO vo = new BookAuthorVO();
        BeanUtils.copyProperties(bookAuthor, vo);

        // 设置关联数据
        try {
            if (bookAuthor.getBookId() != null) {
                Book book = bookMapper.selectById(bookAuthor.getBookId());
                if (book != null) {
                    vo.setBookTitle(book.getTitle());
                    vo.setBookIsbn(book.getIsbn());
                }
            }

            if (bookAuthor.getAuthorId() != null) {
                Author author = authorMapper.selectById(bookAuthor.getAuthorId());
                if (author != null) {
                    vo.setAuthorName(author.getName());
                    vo.setAuthorNameEn(author.getNameEn());
                    vo.setAuthorPenName(author.getPenName());
                    vo.setAuthorAvatar(author.getAvatar());
                    vo.setAuthorNationality(author.getNationality());
                }
            }

        } catch (Exception e) {
            log.warn("获取图书作者关联数据失败，关联ID：{}", bookAuthor.getId(), e);
        }

        return vo;
    }
}
